<?php

namespace Xin\Wechat;

use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
use EasyWeChat\OpenPlatform\Contracts\Application as ApplicationInterface;
use Xin\Capsule\WithConfig;
use Xin\Wechat\Contracts\Factory as WechatFactory;
use Xin\Wechat\Exceptions\WechatInvalidConfigException;

/**
 * @template A of ApplicationInterface
 */
class WechatManager implements WechatFactory
{
	use WithConfig, HasOpenPlatform, HasOfficialAccount, HasMiniApp, HasWork, HasOpenWork;

	/**
	 * @var array
	 */
	protected $config = [];

	/**
	 * WechatManager constructor.
	 *
	 * @param array $config
	 */
	public function __construct(array $config)
	{
		$this->config = $config;
	}

	/**
	 * @inheritDoc
	 * @throws InvalidArgumentException
	 */
	public function openPlatform($name = null, array $options = [])
	{
		$name = $name ?: $this->getDefaultOpenPlatform();

		return $this->makeOpenPlatform($this->getOpenPlatformConfig($name), $options);
	}

	/**
	 * @inheritDoc
	 */
	public function hasOpenPlatform($name = null)
	{
		$name = $name ?: $this->getDefaultOpenPlatform();

		return $this->hasOpenPlatformConfig($name);
	}

	/**
	 * @inheritDoc
	 * @throws InvalidArgumentException
	 */
	public function officialAccount($name = null, array $options = [])
	{
		$name = $name ?: $this->getDefaultOfficialAccount();

		return $this->makeOfficialAccount($this->getOfficialAccountConfig($name), $options);
	}

	/**
	 * @inheritDoc
	 */
	public function hasOfficialAccount($name = null)
	{
		$name = $name ?: $this->getDefaultOpenPlatform();

		return $this->hasOfficialAccountConfig($name);
	}

	/**
	 * @inheritDoc
	 */
	public function miniApp($name = null, array $options = [])
	{
		$name = $name ?: $this->getDefaultMiniApp();

		return $this->makeMiniApp($this->getMiniAppConfig($name), $options);
	}

	/**
	 * @inheritDoc
	 */
	public function hasMiniApp($name = null)
	{
		$name = $name ?: $this->getDefaultMiniApp();
		return $this->hasMiniAppConfig($name);
	}

	/**
	 * @inheritDoc
	 */
	public function miniProgram($name = null, array $options = [])
	{
		return $this->miniApp($name, $options);
	}

	/**
	 * @inheritDoc
	 */
	public function hasMiniProgram($name = null)
	{
		return $this->hasMiniApp($name);
	}

	/**
	 * @inheritDoc
	 */
	public function work($name = null, array $options = [])
	{
		$name = $name ?: $this->getDefaultWork();

		return $this->makeWork($this->getWorkConfig($name), $options);
	}

	/**
	 * @inheritDoc
	 */
	public function hasWork($name = null)
	{
		$name = $name ?: $this->getDefaultWork();

		return $this->hasWorkConfig($name);
	}

	/**
	 * @inheritDoc
	 * @throws InvalidArgumentException
	 */
	public function openWork($name = null, array $options = [])
	{
		$name = $name ?: $this->getDefaultOpenWork();

		return $this->makeOpenWork($this->getOpenPlatformConfig($name), $options);
	}

	/**
	 * @inheritDoc
	 */
	public function hasOpenWork($name = null)
	{
		return $this->hasOpenWorkConfig($name);
	}

	/**
	 * @inheritDoc
	 */
	public function openPlatformShouldUse(string $name)
	{
		$this->setConfig('defaults.open_platform', $name);
	}

	/**
	 * @inheritDoc
	 */
	public function officialAccountShouldUse(string $name)
	{
		$this->setConfig('defaults.official_account', $name);
	}


	/**
	 * @inheritDoc
	 */
	public function miniAppShouldUse(string $name)
	{
		$this->setConfig('defaults.mini_app', $name);
	}


	/**
	 * @inheritDoc
	 */
	public function workShouldUse(string $name)
	{
		$this->setConfig('defaults.work', $name);
	}


	/**
	 * @inheritDoc
	 */
	public function openWorkShouldUse(string $name)
	{
		$this->setConfig('defaults.open_work', $name);
	}

	/**
	 * 检查配置是否正确
	 *
	 * @param array $config
	 * @return array
	 */
	protected function checkApplicationConfig(array $config)
	{
		if (!isset($config['app_id']) || empty($config['app_id'])) {
			throw new WechatInvalidConfigException("wechat config 'app_id' not defined.");
		}

		if (!isset($config['mode']) || $config['mode'] == 0) {
			if (!isset($config['secret']) || empty($config['secret'])) {
				throw new WechatInvalidConfigException("wechat config 'secret' not defined.");
			}
		} else {
			if (!isset($config['authorizer_refresh_token']) || empty($config['authorizer_refresh_token'])) {
				throw new WechatInvalidConfigException("wechat config 'authorizer_refresh_token' not defined.");
			}
		}

		return array_replace_recursive([
			'http' => $this->getConfig('http', []),
		], $config);
	}


	/**
	 * @param A $app
	 * @param array $options
	 * @return A
	 */
	protected function initApplication($app, array $options)
	{
		//// 监听微信响应数据
		//$app->events->addListener(HttpResponseCreated::class, function(HttpResponseCreated $event){
		//	$response = $event->response;
		//
		//	if(false !== stripos($response->getHeaderLine('Content-disposition'), 'attachment')){
		//		$response = StreamResponse::buildFromPsrResponse($response);
		//	}else{
		//		$response = Response::buildFromPsrResponse($response);
		//	}
		//});

		// $app->logger->extend('api_log', function ($app, $config) {
		// 	return new Monolog('WechatApiLog', [
		// 		new ApiLogHandler($app, $config),
		// 	]);
		// });

		return $app;
	}

}
